#include "audio_assets.h" // 嵌入式音频头文件
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

// 全局控制变量
volatile int stop_audio = 0;
const AudioAsset *g_selected_audio = NULL;
int pipefd[2];         // 管道：[0]读端，[1]写端
pid_t ffplay_pid = -1; // ffplay子进程ID

/**
 * 随机选择嵌入式音频
 */
void random_select_mp3() {
  int rand_idx = rand() % AUDIO_ASSET_COUNT;
  g_selected_audio = &audio_assets[rand_idx];
  printf("[音频] 选中嵌入式音频（索引：%d，大小：%u字节）\n", rand_idx,
         g_selected_audio->len);
}

/**
 * 音频播放线程：通过管道将内存数据传给ffplay
 */
void *audio_play_thread(void *arg) {
  // 1. 创建管道（用于父子进程通信）
  if (pipe(pipefd) == -1) {
    perror("[错误] 管道创建失败");
    return NULL;
  }

  // 2. 创建子进程，启动ffplay从管道读取数据
  ffplay_pid = fork();
  if (ffplay_pid == -1) {
    perror("[错误] 创建子进程失败");
    close(pipefd[0]);
    close(pipefd[1]);
    return NULL;
  }

  if (ffplay_pid == 0) { // 子进程：执行ffplay
    close(pipefd[1]);    // 子进程关闭写端

    // 将管道读端重定向到标准输入（ffplay默认从stdin读取）
    if (dup2(pipefd[0], STDIN_FILENO) == -1) {
      perror("[子进程错误] 重定向标准输入失败");
      exit(EXIT_FAILURE);
    }
    close(pipefd[0]); // 重定向后关闭原读端

    // 启动ffplay：-i - 表示从标准输入读取，-autoexit播放完自动退出
    execlp("ffplay", "ffplay", "-hide_banner", "-nodisp", "-autoexit", "-i",
           "-", NULL);

    // 如果execlp失败（如ffplay未安装）
    perror("[子进程错误] 启动ffplay失败（请先安装ffmpeg）");
    exit(EXIT_FAILURE);
  } else {            // 父进程：将内存数据写入管道
    close(pipefd[0]); // 父进程关闭读端

    // 3. 将嵌入式音频数据写入管道（分块写，避免管道缓冲区溢出）
    const size_t chunk_size = 4096; // 每次写4KB
    size_t total_written = 0;
    const u_int8_t *data = g_selected_audio->data;
    const size_t total_len = g_selected_audio->len;

    printf("[音频] 开始向ffplay传输数据（总大小：%u字节）\n", total_len);
    while (total_written < total_len && !stop_audio) {
      size_t write_len = (total_len - total_written) > chunk_size
                             ? chunk_size
                             : (total_len - total_written);

      ssize_t ret = write(pipefd[1], data + total_written, write_len);
      if (ret == -1) {
        perror("[错误] 管道写入失败");
        break;
      }
      total_written += ret;
    }

    // 4. 写完数据后关闭写端，让ffplay知道数据结束
    close(pipefd[1]);
    printf("[音频] 数据传输完成（已写：%zu字节）\n", total_written);

    // 5. 等待ffplay播放完成
    int status;
    waitpid(ffplay_pid, &status, 0);
    printf("[音频] ffplay播放结束（退出状态：%d）\n", WEXITSTATUS(status));
  }

  stop_audio = 1;
  return NULL;
}

/**
 * 信号处理：停止播放并清理
 */
void sig_handler(int sig) {
  stop_audio = 1;
  if (ffplay_pid != -1) {
    kill(ffplay_pid, SIGTERM); // 终止ffplay子进程
  }
  exit(0);
}

// -------------------------- 主函数（测试用） --------------------------
int main() {
  srand(time(NULL));
  signal(SIGINT, sig_handler); // 捕获Ctrl+C

  // 选择嵌入式音频
  random_select_mp3();

  // 创建并启动音频播放线程
  pthread_t audio_thread;
  if (pthread_create(&audio_thread, NULL, audio_play_thread, NULL) != 0) {
    perror("[错误] 创建音频线程失败");
    return 1;
  }

  // 等待播放结束（或用户中断）
  pthread_join(audio_thread, NULL);
  printf("[主程序] 退出\n");
  return 0;
}
